;
; PROGRAM: DPROG
; AUTHOR: Richard Conn
; VERSION: 1.0
; DATE: 28 July 84
; PREVIOUS VERSIONS: None
;
vers	equ	10
z3env	equ	0f400h

;
;	DPROG is used to program the user's terminal, printer, or punch
; with data from the file specified in the command line.  DPROG will
; automatically search for the file along the path starting at the
; indicated (or implied) DU.
;

;
;  Basic Equates
;
opsys	equ	0
fcb	equ	5ch
tbuff	equ	80h
cr	equ	0dh
ff	equ	0ch
lf	equ	0ah
ctrlc	equ	'C'-'@'
ctrls	equ	'S'-'@'
ctrlz	equ	'Z'-'@'
bel	equ	7
bs	equ	8
tab	equ	9

;
;  DPROG Constants
;
COMMENT	equ	';'	;denotes a comment line
WORD	equ	'-'	;denotes a word definition
SYM	equ	'='	;symbol table dump command
DEV	equ	'>'	;device assignment
INP	equ	'<'	;input forms (pause, string, delay)
wordl	equ	16	;length of word
fmt	equ	'('	;begin format definition
fmtch	equ	'%'	;format escape char
endfmt	equ	')'	;end format definition
quote	equ	'"'	;quote string
literal	equ	'\'	;literal interpretation follows
control	equ	'^'	;control char follows

;
;  SYSLIB Routines
;
	ext	condin,cin,cout,lout,pout
	ext	z3init,pfind,z3log
	ext	moveb,hmovb,logud,pfn1,caps
	ext	f$open,f$read,f$close
	ext	eval,pafdc,pa2hc
	ext	codend

;
; Environment Definition
;
	if	z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
	jmp	start
	db	'Z3ENV'	;This is a ZCPR3 Utility
	db	1	;External Environment Descriptor
z3eadr:
	dw	z3env
start:
	lhld	z3eadr	;pt to ZCPR3 environment
;
	else
;
; Internal ZCPR3 Environment Descriptor
;
	MACLIB	Z3BASE.LIB
	MACLIB	SYSENV.LIB
z3eadr:
	jmp	start
	SYSENV
start:
	lxi	h,z3eadr	;pt to ZCPR3 environment
	endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
	call	z3init	;initialize the ZCPR3 Env
;
; Initial Routines
;
	call	helpck	;check for help
	call	bufinit	;initialize buffers
;
; Load File
;
	call	locfile	;locate file
	call	logud	;enter directory of file
	call	load	;load file
;
; Perform Program
;
	call	program	;program the user's terminal
	ret

;
; Initialize Buffers
;
bufinit:
	call	codend	;address of free space
	shld	format	;format string
	xchg
	lxi	h,deffmt	;set default format (char)
	mvi	b,40	;allow 40 chars
	call	moveb
	xchg		;HL pts to format buffer
	inr	h	;next page
	shld	locstk	;set location stack
	shld	tos	;set top of stack
	mvi	m,0
	inx	h
	mvi	m,0	;zero stack
	dcx	h
	inr	h	;next page
	shld	free	;free area
	mvi	a,'C'	;assign console as output device
	sta	outdev
	ret

;
; Check for Help
;
helpck:
	lxi	h,fcb+1	;pt to fcb name
	mov	a,m	;get it
	cpi	'/'	;help if slash
	rnz
	pop	psw	;clear stack
	call	eprint
	db	'DPROG, Version '
	db	(vers/10)+'0','.',(vers mod 10)+'0'
	db	cr,lf,' Syntax:'
	db	cr,lf,'  DPROG              <-- STD.DPG'
	db	cr,lf,'  DPROG filename     <-- filename.DPG'
	db	cr,lf,'  DPROG filename.typ <-- filename.typ'
	db	0
	ret

;
; Find File
;   If found, return BC=DU and NZ
;
locfile:
	lxi	d,fcb	;pt to FCB
	call	z3log
	lxi	d,fcb+1	;pt to file name
	lxi	h,defname	;pt to default file name
	mvi	b,8	;8 chars
	ldax	d	;any type?
	cpi	' '	;none if space
	cz	moveb
	lxi	d,fcb+9	;pt to file type
	lxi	h,deftype	;pt to default file type
	mvi	b,3	;3 chars
	ldax	d	;any type?
	cpi	' '	;none if space
	cz	moveb
	lxi	d,fcb	;pt to FCB
	mvi	a,0ffh	;search current
	call	pfind	;search for file
	rnz		;get file if found
;
; Abort Attempt to Load File
;
abort:
	pop	psw	;clear stack
	call	eprint
	db	cr,lf,' File ',0
	lxi	d,fcb+1	;pt to file name
	call	pfn1
	call	eprint
	db	' NOT Found',0
	ret

;
; Load File
;
load:
	lxi	d,fcb	;pt to fcb
	call	f$open	;open file for input
	jnz	abort	;abort attempt
	lhld	free	;buffer area
load1:
	lxi	d,fcb	;pt to fcb
	call	f$read	;read next block
	jnz	load2	;done, so mark and close
	lxi	d,tbuff	;copy into buffer
	xchg		;copy into buffer at DE from TBUFF at HL
	mvi	b,128	;128 bytes
	call	moveb
	lxi	h,80h	;pt to next buffer
	dad	d
	jmp	load1
load2:
	mvi	m,ctrlz	;mark EOF
	inr	h	;next page
	mvi	l,0
	shld	words	;mark beginning of word definition area
	shld	nxtword	;mark next word
	mvi	m,0	;mark no words
	jmp	f$close	;close input file

;
; Program the User's Terminal
;
program:
	lhld	free	;pt to first char
prog1:
	call	capa	;capitalize
	cpi	ctrlz	;done?
	rz
	cpi	CR	;eol?
	jz	skipl
	cpi	WORD	;word definition?
	jz	defword
	cpi	SYM	;symbol table or format definition dump?
	jz	dump
	cpi	DEV	;assign device?
	jz	device
	cpi	INP	;input form?
	jz	input
	push	h	;save HL
prog2:
	call	output	;output line at HL
	call	locpop	;pop stack if any
	jnz	prog2	;continue if any element on stack
	pop	h	;restore HL
;
; Skip to next line
;
skipl:
	mov	a,m	;get char
	call	capa	;capitalize
	cpi	CR	;new line?
	jz	skipl1
	cpi	LF	;new line?
	jz	skipl1
	cpi	CTRLZ	;EOF?
	rz
	inx	h	;pt to next
	jmp	skipl
skipl1:
	mov	a,m	;get it
	inx	h	;pt to next
	ani	7fh	;mask
	cpi	CR	;continue?
	jz	skipl1
	cpi	LF	;continue?
	jz	skipl1
	dcx	h	;pt to non-eol char
	jmp	prog1	;continue with next line
;
; Input Form
;
input:
	inx	h	;pt to next char
	call	cin	;get any char
	ani	7fh	;mask
	cpi	ctrlc	;abort?
	jz	opsys
	jmp	skipl	;continue
;
; Assign Device
;
device:
	inx	h	;pt to char
	call	capa	;capitalize
	cpi	'C'	;console?
	jz	setdev
	cpi	'L'	;list?
	jz	setdev
	cpi	'P'	;punch?
	jz	setdev
	push	psw
	call	eprint
	db	cr,lf,bel,' Invalid Device Assignment: ',0
	pop	psw
	call	cout	;print char
	dcx	h	;back up
	jmp	skipl	;continue
;
; Perform assignment
;
setdev:
	sta	outdev	;assign
	jmp	skipl	;continue
;
; Define Word
;
defword:
	inx	h	;pt to first char of word
	call	bufword	;store word in buffer
	shld	nextch	;save ptr to next char
	call	wscan	;scan for word
	jz	defnew	;new word defined
	xchg		;ptr to high-order in DE
	lhld	nextch	;get ptr to word definition
	xchg		;word defn in DE, word adr high in HL
	mov	m,d	;store new address
	dcx	h
	mov	m,e
	xchg		;HL pts to word
	jmp	skipl	;skip out line
;
; New Word
;
defnew:
	lhld	nxtword		;pt to next word
	xchg
	lxi	h,wordbf	;pt to buffer
	mvi	b,wordl		;number of chars max
	call	hmovb		;copy into buffer and advance HL
	lhld	nextch		;get address
	xchg
	mov	m,e		;put low
	inx	h
	mov	m,d		;put high
	inx	h		;set ptr to next word
	mvi	m,0		;store zero
	shld	nxtword		;set ptr
	xchg			;HL pts to word definition
	jmp	skipl		;skip to next line

;
; Dump Format String or Word Table
;
dump:
	inx	h	;pt to option
	call	capa	;check for format display option
	cpi	'F'	;format?
	jz	dfmt	;dump format if so
	cpi	'S'	;symbols?
	jz	dsym
	dcx	h	;pt to current
	call	dumpsym	;dump symbols
	call	dumpfmt	;dump format
	jmp	skipl	;continue
;
; Dump Format
;
dfmt:
	call	dumpfmt	;do dump
	jmp	skipl	;continue
;
; Dump Words
;
dsym:
	call	dumpsym	;do dump
	jmp	skipl	;continue
;
; Dump Words in Symbol Table
;
dumpsym:
	push	h	;save HL
	call	eprint
	db	cr,lf,' >> Word Definitions <<',0
	lhld	words	;dump word table
sym1:
	mov	a,m	;get next
	ora	a
	jz	symexit
	call	eprint
	db	cr,lf,'  ',0
	call	prword	;print word
	mov	e,m	;get low
	inx	h
	mov	d,m	;get high
	inx	h	;pt to next word
	push	h	;save ptr
	call	eprint
	db	'  >',0
	xchg		;HL pts to word
sym2:
	mov	a,m	;get next char
	cpi	CR	;done?
	jz	sym3
	cpi	TAB	;translate tab to space
	jnz	sym2out
	mvi	a,' '	;space instead of tab
sym2out:
	call	chout
	inx	h
	jmp	sym2
sym3:
	call	eprint
	db	'<',0
	pop	h	;pt to next word
	jmp	sym1
symexit:
	pop	h	;pt to char
	ret
;
; Output Format String
;
dumpfmt:
	push	h	;save ptr
	call	eprint
	db	cr,lf,' Format: (',0
	lhld	format	;pt to string
	call	epstr	;print it
	call	eprint
	db	')',cr,lf,0
	pop	h	;get ptr
	ret

;
; Print Word at HL (advance HL)
;
prword:
	mvi	b,wordl	;number of chars
prw1:
	mov	a,m	;get char
	call	chout
	inx	h
	dcr	b
	jnz	prw1
	ret
;
; Routine to Output a Line
;
output:
	call	sksp	;skip spaces
	cpi	COMMENT	;done?
	rz
	cpi	CR	;done?
	rz
	cpi	LF	;done?
	rz
	cpi	CTRLZ	;done?
	rz
	cpi	fmt	;format definition?
	jz	outfmt
	cpi	quote	;chars?
	jz	outch
	call	bufword	;store word in buffer
	shld	nextch	;save ptr to next char after word
	call	wscan	;scan for word in table
	jz	badword	;word not defined
	call	locpush	;push location onto stack
	xchg		;HL pts to continuation location
	jmp	output	;continue
;
; Output Quoted String
;
outch:
	inx	h	;pt to next char
outch1:
	mov	a,m	;get it
	ani	7fh	;mask
	cpi	CR	;done?
	jz	outcherr
	cpi	LF	;done?
	jz	outcherr
	cpi	CTRLZ	;done?
	jz	outcherr
	cpi	quote	;end of quote?
	jz	outch2
	call	charout	;output char in whatever form
	jmp	outch1	;continue
outcherr:
	call	eprint
	db	cr,lf,bel,' Premature End of Quote',cr,lf,0
	jmp	output
outch2:
	inx	h	;pt to after quote
	jmp	output	;continue
;
; Output char in A and set HL to next char on exit
;
charout:
	cpi	control	;control char follows?
	jz	charo0
	cpi	literal	;literal follows?
	jz	charo1
;
; Normal Char in A
;
charnxt:
	inx	h		;pt to next char
	jmp	formatout	;output with format
;
; Output control char
;
charo0:
	inx	h	;pt to char
	call	capa	;get char
	sui	'@'	;convert to control
	jc	ctrlerr
	cpi	20h
	jnc	ctrlerr
	inx	h	;pt to next
	jmp	formatout
ctrlerr:
	call	eprint
	db	cr,lf,bel,' Invalid Control Character',cr,lf,0
	ret
;
; Output Literal Format
;
charo1:
	inx	h	;pt to char
	call	capa	;get char
	cpi	'B'	;BS?
	jz	c1bs
	cpi	'D'	;DEL?
	jz	c1del
	cpi	'E'	;ESCAPE?
	jz	c1esc
	cpi	'L'	;CRLF?
	jz	c1nl
	cpi	'N'	;LF?
	jz	c1lf
	cpi	'R'	;CR?
	jz	c1cr
	cpi	'T'	;TAB?
	jz	c1tab
	cpi	'0'	;digit?
	jc	charol	;literal if not
	cpi	'9'+1	;range?
	jc	numout
	cpi	' '	;less than space?
	jnc	charol
	call	eprint
	db	cr,lf,bel,' Invalid Literal Argument',cr,lf,0
	ret

;
; Output Char in A literally
;
charol:
	mov	a,m	;get char
	ani	7fh	;don't cap this way
	inx	h	;pt to next
	jmp	formatout
;
; Output Number
;
numout:
	call	eval	;convert to binary in DE
	mov	a,e	;char binary value
	jmp	formatout	;output with format
;
; Output BS
;
c1bs:
	mvi	a,bs
	jmp	charnxt
;
; Output TAB
;
c1tab:
	mvi	a,tab
	jmp	charnxt
;
; Output CR
;
c1cr:
	mvi	a,cr
	jmp	charnxt
;
; Output DEL
;
c1del:
	mvi	a,7fh
	jmp	charnxt
;
; Output ESCAPE
;
c1esc:
	mvi	a,1bh
	jmp	charnxt
;
; Output LF
;
c1lf:
	mvi	a,lf
	jmp	charnxt
;
; Output CRLF
;
c1nl:
	mvi	a,cr
	call	formatout	;output CR
	mvi	a,lf
	jmp	charnxt

;
; Output Char in A According to Format
;
formatout:
	push	h	;save ptr to next char
	push	b	;save BC
	mov	b,a	;char in B
	lhld	format	;pt to format string
fout1:
	mov	a,m	;get next char
	ani	7fh	;mask
	jz	foutx	;exit if end of string
	cpi	fmtch	;expression form?
	jz	fout2
	cpi	literal	;literal?
	jz	flit
;
; Output char in A and advance
;
fch:
	call	chout	;output char
	inx	h	;pt to next
	jmp	fout1
;
; Output Value in B according to format
;
fout2:
	inx	h	;pt to format type
	mov	a,m	;get char
	inx	h	;pt to next
	ani	7fh	;mask
	call	caps
	ora	a	;none?
	jz	fout1	;error condition - % at end of string
	cpi	'C'	;char?
	jz	foch
	cpi	'D'	;floating decimal chars
	jz	fod
	cpi	'2'	;2 decimal chars
	jz	fo2
	cpi	'3'	;3 decimal chars
	jz	fo3
	cpi	'X'	;2 hex chars
	jz	fox
	push	psw
	call	eprint
	db	cr,lf,bel,' Invalid Format Char: ',0
	pop	psw
	call	cout
	call	crlf
	jmp	fout1	;continue

;
; Output value in B as char
;
foch:
	mov	a,b	;get value
	call	chout	;output it
	jmp	fout1	;continue
;
; Output value in B as floating decimal
;
fod:
	mov	a,b	;get value
	call	pafdc	;output
	jmp	fout1	;continue
;
; Output value in B as hex
;
fox:
	mov	a,b	;get value
	call	pa2hc	;output
	jmp	fout1	;continue
;
; Output value in B as 3 decimal chars
;
fo3:
	mvi	c,100	;100's
	call	dec	;output and fall thru to FO2
;
; Output value in B as 2 decimal chars
;
fo2:
	mvi	c,10	;10's
	call	dec
	mov	a,b	;get value
	adi	'0'	;convert
	call	chout
	jmp	fout1	;continue
;
; Subtracting Output
;   Output value in B as 100's or 10's digit (leading 0 allowed)
;
dec:
	push	d	;save DE
	mov	a,b	;get value
	mvi	d,'0'	;set digit
dec1:
	sub	c	;subtract
	jc	dec2
	inr	d	;increment digit
	jmp	dec1
dec2:
	add	c	;add back in
	mov	b,a
	mov	a,d	;output digit
	call	chout
	pop	d	;restore DE
	ret
;
; Exit Format String Output
;
foutx:
	pop	b	;restore BC
	pop	h	;restore ptr to next char
	ret
;
; Literal Format Output
;
flit:
	inx	h	;pt to char
	call	capa	;get char
	cpi	'B'	;BS?
	jz	f1bs
	cpi	'D'	;DEL?
	jz	f1del
	cpi	'E'	;ESCAPE?
	jz	f1esc
	cpi	'L'	;CRLF?
	jz	f1nl
	cpi	'N'	;LF?
	jz	f1lf
	cpi	'R'	;CR?
	jz	f1cr
	cpi	'T'	;TAB?
	jz	f1tab
	cpi	'0'	;digit?
	jc	fchck	;literal if not
	cpi	'9'+1	;range?
	jnc	fchck
;
; Output Number
;
	call	eval	;convert to binary in DE
	mov	a,e	;char binary value
	jmp	fch	;output
;
; Check for Valid Literal
;
fchck:
	cpi	' '	;not valid if less than space
	jnc	fch
	call	eprint
	db	cr,lf,bel,' Invalid Literal Argument',cr,lf,0
	jmp	fout1
;
; Output BS
;
f1bs:
	mvi	a,bs
	jmp	fch
;
; Output TAB
;
f1tab:
	mvi	a,tab
	jmp	fch
;
; Output CR
;
f1cr:
	mvi	a,cr
	jmp	fch
;
; Output DEL
;
f1del:
	mvi	a,7fh
	jmp	fch
;
; Output ESCAPE
;
f1esc:
	mvi	a,1bh
	jmp	fch
;
; Output LF
;
f1lf:
	mvi	a,lf
	jmp	fch
;
; Output CRLF
;
f1nl:
	mvi	a,cr
	call	chout	;output CR
	mvi	a,lf
	jmp	fch

;
; Define New Output Format
;
outfmt:
	inx	h	;pt to format char
	xchg
	lhld	format	;pt to format area
	xchg
;
; Get next char for format string
;
outf1:
	mov	a,m	;get next char
	ani	7fh	;mask
	cpi	endfmt	;end of format?
	jz	outf2
	cpi	CR	;end of line?
	jz	outf3
	cpi	LF	;end of line?
	jz	outf3
	cpi	CTRLZ	;end of file?
	jz	outf3
	stax	d	;store char
	inx	h	;pt to next
	inx	d
	cpi	literal	;literal denotation?
	jnz	outf1	;continue if not
;
; Literal flag, so store next char exactly as-is without interpretation
;
	mov	a,m	;get next char
	ani	7fh	;mask
	stax	d	;store it literally
	inx	h	;pt to next
	inx	d
	jmp	outf1
;
; Format String Stored - Terminate it
;
outf2:
	inx	h	;pt to next char
outf3:
	xra	a	;terminate format string
	stax	d
	jmp	output

;
; Invalid Word - So State
;
badword:
	call	eprint
	db	cr,lf,bel,' Invalid Word Reference: ',0
	lxi	h,wordbf	;pt to buffer
	call	prword		;print word
	lhld	nextch		;continue
	jmp	output
;
; Element must be a word - resolve it
;
bufword:
	lxi	d,wordbf	;buffer to store word in
	mvi	b,wordl		;length
;
; Build Word into WORDBF
;
bword1:
	call	capa		;get char
	cpi	' '+1		;end?
	jc	bword3
	stax	d		;store char
	inx	h		;pt to next
	inx	d
	dcr	b		;count down
	jnz	bword1
;
; Word is longer than WORDL - skip trailing chars
;
bword2:
	mov	a,m		;skip chars to delimiter
	ani	7fh		;mask
	cpi	' '+1
	jc	bword4
	inx	h		;pt to next
	jmp	bword2
;
; Word is built into WORDBF - space fill it
;
bword3:
	mvi	a,' '		;space
	stax	d		;store char
	inx	d		;pt to next
	dcr	b		;count down
	jnz	bword3
;
; Word is Stored
;   HL pts to next char after the Word
;
bword4:
	ret
;
; Scan for Word in Table
;   Return with Zero Set if Not Resolved
;   If Resolved, DE=address of word
;
wscan:
	lhld	words		;pt to first word in table
wscan1:
	mov	a,m		;abort if empty table
	ora	a
	rz
	lxi	d,wordbf	;pt to buffer
	mvi	b,wordl		;size of buffer
	push	h		;save HL
wscan2:
	ldax	d		;get char
	cmp	m		;compare
	jnz	wscan3
	inx	h		;pt to next
	inx	d
	dcr	b		;count down
	jnz	wscan2
	mov	e,m		;get address in DE
	inx	h
	mov	d,m
	pop	psw		;clear stack
	xra	a		;return NZ
	dcr	a
	ret
wscan3:
	pop	h		;get address of current word in table
	lxi	d,wordl+2	;advance to next word
	dad	d
	jmp	wscan1

;
; Push Address in NEXTCH onto Location Stack
;
locpush:
	push	h	;save regs
	push	d
	lhld	nextch	;get address
	xchg		;... in DE
	lhld	tos	;get top of stack
	mov	m,e	;store address
	inx	h
	mov	m,d
	inx	h
	shld	tos	;new top of stack
	pop	d	;restore regs
	pop	h
	ret
;
; Pop Address from Top of Stack
;
locpop:
	lhld	locstk	;local stack
	xchg
	lhld	tos	;check to see if nothing on stack
	mov	a,e	;if lows are same, nothing on stack
	cmp	l
	rz
	dcx	h	;pt to top element
	mov	d,m	;get high
	dcx	h
	mov	e,m	;get low
	shld	tos	;new top of stack
	xchg		;address in HL
	xra	a	;return with NZ
	dcr	a
	ret
;
; Skip to Non-Space
;
sksp:
	mov	a,m	;get char
	ani	7fh	;mask
	call	issp	;test for space
	rnz		;not space, so return
	inx	h	;pt to next
	jmp	sksp
;
; Test char in A for space char
;   Ret with Z if yes
;
issp:
	push	h	;save HL
	push	b	;save BC
	lxi	h,sptab	;pt to table
	mov	b,a	;char in B
issp1:
	mov	a,m	;get next char
	ora	a	;end of table?
	jz	issp3
	cmp	b	;match?
	jz	issp2
	inx	h	;pt to next
	jmp	issp1
issp2:
	mov	a,b	;restore char
	pop	b	;restore regs
	pop	h
	ret		;Z flag is set
issp3:
	xra	a	;set NZ
	dcr	a
	jmp	issp2
;
; Output New Line
;
crlf:
	push	psw	;save A
	mvi	a,cr	;CR
	call	chout
	mvi	a,lf	;LF
	call	chout
	pop	psw	;get A
	ret
;
; Output Char in A with XON/XOFF Flow Control
;
chout:
	push	psw	;save char
	call	condin	;conditional input
	jz	chout1
	cpi	ctrls	;pause?
	jnz	chout1
	call	cin	;wait for following char
chout1:
	pop	psw	;get char
	push	b	;save BC
	mov	c,a	;char in C
	lda	outdev	;get output device
	cpi	'C'	;console?
	jz	chcon
	cpi	'L'	;printer?
	jz	chlst
	cpi	'P'	;punch?
	jz	chpun
;
; Output to Console
;
chcon:
	mov	a,c	;get char
	call	cout
	pop	b
	ret
;
; Output to List
;
chlst:
	mov	a,c	;get char
	call	lout
	pop	b
	ret
;
; Output to Punch
;
chpun:
	mov	a,c	;get char
	call	pout
	pop	b
	ret
;
; Print String Pted to by HL
;
epstr:
	mov	a,m	;get char
	inx	h	;pt to next
	ani	7fh	;mask MSB
	rz		;done
	call	chout	;print char
	jmp	epstr
;
; Print String at Return Address
;
eprint:
	xthl		;save HL and pt to string
	call	epstr	;print string
	xthl		;restore HL and new exec adr
	ret
;
; Input Char, Mask, and Capitalize
;
capa:
	mov	a,m	;get char
	ani	7fh	;mask
	jmp	caps	;capitalize

;
; Space Table
;
sptab:
	db	' ',tab,bs,ff,',','.',0	;space chars

;
; Data Area
;
defname:
	db	'STD     '	;default file name
deftype:
	db	'DPG'		;default file type
deffmt:
	db	'%C',0	;default format string
outdev:
	ds	1	;output device (C=console, L=list, P=punch)
outdev1:
	ds	1	;save area for output device
wordbf:
	ds	wordl	;current word buffer
format:
	ds	2	;address of format string
free:
	ds	2	;address of free area
words:
	ds	2	;address of scratch area
nxtword:
	ds	2	;pointer to next word
nextch:
	ds	2	;pointer to next char
locstk:
	ds	2	;pointer to location stack
tos:
	ds	2	;pointer to top of stack

	end
